/*
 * Copyright (C) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <queue>
#include "gtest/gtest.h"
#include "filter/filter.h"
#include "media_sync_manager.h"

#include "video_sink.h"
#include "media_synchronous_sink.h"

using namespace testing::ext;

namespace OHOS {
namespace Media {
namespace Test {
using namespace Pipeline;
class TestSyncManager : public testing::Test {
public:
    // SetUpTestCase: Called before all test cases
    static void SetUpTestCase(void) { }
    // TearDownTestCase: Called after all test case
    static void TearDownTestCase(void) { }
    // SetUp: Called before each test cases
    void SetUp(void)
    {
        syncManager_ = std::make_shared<MediaSyncManager>();
        ASSERT_TRUE(syncManager_ != nullptr);
    }
    // TearDown: Called after each test cases
    void TearDown(void)
    {
        syncManager_ = nullptr;
    }
public:
    std::shared_ptr<MediaSyncManager> syncManager_ = nullptr;
};

HWTEST_F(TestSyncManager, sync_manager_set, TestSize.Level1)
{
    float rate = 0;
    auto setPlaybackRateStatus = syncManager_->SetPlaybackRate(rate);
    ASSERT_EQ(setPlaybackRateStatus, Status::OK);
}

HWTEST_F(TestSyncManager, sync_manager_get, TestSize.Level1)
{
    auto rateBack = syncManager_->GetPlaybackRate();
    ASSERT_EQ(rateBack, 1);
}

HWTEST_F(TestSyncManager, sync_manager_life_cycle, TestSize.Level1)
{
    // Resume
    auto resumeStatus = syncManager_->Resume();
    ASSERT_EQ(resumeStatus, Status::OK);

    // Pause
    auto pauseStatus = syncManager_->Pause();
    ASSERT_EQ(pauseStatus, Status::OK);

    // Seek
    int64_t seekTime = 0;
    auto seekStatus = syncManager_->Seek(seekTime);
    ASSERT_NE(seekStatus, Status::OK);

    // Reset
    auto resetStatus = syncManager_->Reset();
    ASSERT_EQ(resetStatus, Status::OK);

    // IsSeeking
    auto isSeeking = syncManager_->InSeeking();
    ASSERT_EQ(isSeeking, false);
}

HWTEST_F(TestSyncManager, sync_manager_update_time_without_synchronizer, TestSize.Level1)
{
    // AddSynchronizer
    VideoSink sync;
    syncManager_->AddSynchronizer(&sync);
    // RemoveSynchronizer
    syncManager_->RemoveSynchronizer(&sync);
    // UpdateTimeAnchor
    auto updateTimeStatus = syncManager_->UpdateTimeAnchor(-1, -1, {-1, -1, -1}, nullptr);
    ASSERT_EQ(updateTimeStatus, true);
    updateTimeStatus = syncManager_->UpdateTimeAnchor(1, -1, {-1, -1, -1}, nullptr);
    ASSERT_EQ(updateTimeStatus, true);
    updateTimeStatus = syncManager_->UpdateTimeAnchor(1, 1, {-1, -1, -1}, nullptr);
    ASSERT_EQ(updateTimeStatus, true);
    updateTimeStatus = syncManager_->UpdateTimeAnchor(1, 1, {1, -1, -1}, nullptr);
    ASSERT_EQ(updateTimeStatus, true);
    updateTimeStatus = syncManager_->UpdateTimeAnchor(1, 1, {1, 1, -1}, nullptr);
    ASSERT_EQ(updateTimeStatus, true);
    updateTimeStatus = syncManager_->UpdateTimeAnchor(1, 1, {1, 1, 1}, nullptr);
    ASSERT_EQ(updateTimeStatus, true);
    updateTimeStatus = syncManager_->UpdateTimeAnchor(1, 1, {1, 1, 1}, &sync);
    ASSERT_EQ(updateTimeStatus, true);
}

HWTEST_F(TestSyncManager, sync_manager_life_func, TestSize.Level1)
{
    // AddSynchronizer
    VideoSink sync;
    syncManager_->AddSynchronizer(&sync);
    // UpdateTimeAnchor
    auto updateTimeStatus = syncManager_->UpdateTimeAnchor(-1, -1, {-1, -1, -1}, nullptr);
    ASSERT_EQ(updateTimeStatus, true);
    updateTimeStatus = syncManager_->UpdateTimeAnchor(1, -1, {-1, -1, -1}, nullptr);
    ASSERT_EQ(updateTimeStatus, true);
    updateTimeStatus = syncManager_->UpdateTimeAnchor(1, 1, {-1, -1, -1}, nullptr);
    ASSERT_EQ(updateTimeStatus, true);
    updateTimeStatus = syncManager_->UpdateTimeAnchor(1, 1, {1, -1, -1}, nullptr);
    ASSERT_EQ(updateTimeStatus, true);
    updateTimeStatus = syncManager_->UpdateTimeAnchor(1, 1, {1, 1, -1}, nullptr);
    ASSERT_EQ(updateTimeStatus, true);
    updateTimeStatus = syncManager_->UpdateTimeAnchor(1, 1, {1, 1, 1}, nullptr);
    ASSERT_EQ(updateTimeStatus, true);
    updateTimeStatus = syncManager_->UpdateTimeAnchor(1, 1, {1, 1, 1}, &sync);
    ASSERT_EQ(updateTimeStatus, true);

    // GetMediaTimeNow
    auto mediaTimeNow = syncManager_->GetMediaTimeNow();
    ASSERT_EQ(mediaTimeNow, 0);

    // GetClockTimeNow
    auto clockTimeNow = syncManager_->GetMediaTimeNow();
    ASSERT_EQ(clockTimeNow, 0);

    // GetAnchoredClockTime
    auto clockTime = syncManager_->GetAnchoredClockTime(0);
    ASSERT_NE(clockTime, 0);

    // Report
    syncManager_->ReportPrerolled(&sync);
    syncManager_->ReportEos(&sync);
    syncManager_->SetMediaTimeRangeEnd(0, 0, &sync);
    syncManager_->SetMediaTimeRangeStart(0, 0, &sync);

    // GetSeekTime
    int64_t seekTime = syncManager_->GetSeekTime();
    ASSERT_NE(seekTime, 0);
}

// Scenario1: Test when alreadySetSyncersShouldWait_ is false.
HWTEST_F(TestSyncManager, SetAllSyncShouldWaitNoLock_001, TestSize.Level0)
{
    syncManager_->alreadySetSyncersShouldWait_ = false;
    syncManager_->SetAllSyncShouldWaitNoLock();
    EXPECT_TRUE(syncManager_->prerolledSyncers_.empty());
    EXPECT_TRUE(syncManager_->alreadySetSyncersShouldWait_);
}

// Scenario3: Test when alreadySetSyncersShouldWait_ is true.
HWTEST_F(TestSyncManager, SetAllSyncShouldWaitNoLock_003, TestSize.Level0)
{
    syncManager_->alreadySetSyncersShouldWait_ = true;
    syncManager_->SetAllSyncShouldWaitNoLock();
    EXPECT_TRUE(syncManager_->prerolledSyncers_.empty());
    EXPECT_TRUE(syncManager_->alreadySetSyncersShouldWait_);
}

// Scenario1: Test the normal flow of the Resume method
HWTEST_F(TestSyncManager, Resume_001, TestSize.Level0)
{
    syncManager_->clockState_ = MediaSyncManager::State::RESUMED;
    EXPECT_EQ(syncManager_->Resume(), Status::OK);
}

HWTEST_F(TestSyncManager, Resume_002, TestSize.Level0)
{
    syncManager_->clockState_ = MediaSyncManager::State::PAUSED;
    syncManager_->pausedMediaTime_ = 100;
    syncManager_->alreadySetSyncersShouldWait_ = true;
    EXPECT_EQ(syncManager_->Resume(), Status::OK);
    EXPECT_EQ(syncManager_->pausedMediaTime_, HST_TIME_NONE);
    EXPECT_EQ(syncManager_->pausedClockTime_, HST_TIME_NONE);
}

// Scenario3: Test the flow of the Resume method when clockState is not paused and not resumed
HWTEST_F(TestSyncManager, Resume_003, TestSize.Level0)
{
    syncManager_->clockState_ = MediaSyncManager::State::PAUSED;
    EXPECT_EQ(syncManager_->Resume(), Status::OK);
    EXPECT_EQ(syncManager_->clockState_, MediaSyncManager::State::RESUMED);
}

HWTEST_F(TestSyncManager, Pause_001, TestSize.Level0)
{
    EXPECT_EQ(syncManager_->Pause(), Status::OK);
}

HWTEST_F(TestSyncManager, Pause_002, TestSize.Level0)
{
    syncManager_->clockState_ = MediaSyncManager::State::RESUMED;
    syncManager_->currentAnchorMediaTime_ = 100;
    syncManager_->currentAnchorClockTime_ = 100;
    EXPECT_EQ(syncManager_->Pause(), Status::OK);
}

// Scenario1: Seek when minRangeStartOfMediaTime_ is HST_TIME_NONE
HWTEST_F(TestSyncManager, Seek_ShouldReturnErrorInvalidOperation_WhenMinRangeStartIsNone, TestSize.Level0)
{
    syncManager_->minRangeStartOfMediaTime_ = HST_TIME_NONE;
    syncManager_->maxRangeEndOfMediaTime_ = 100;
    EXPECT_EQ(syncManager_->Seek(50, true), Status::ERROR_INVALID_OPERATION);
}

// Scenario2: Seek when maxRangeEndOfMediaTime_ is HST_TIME_NONE
HWTEST_F(TestSyncManager, Seek_ShouldReturnErrorInvalidOperation_WhenMaxRangeEndIsNone, TestSize.Level0)
{
    syncManager_->minRangeStartOfMediaTime_ = 0;
    syncManager_->maxRangeEndOfMediaTime_ = HST_TIME_NONE;
    EXPECT_EQ(syncManager_->Seek(50, true), Status::ERROR_INVALID_OPERATION);
}

// Scenario3: Seek when isClosest is true
HWTEST_F(TestSyncManager, Seek_ShouldSetFirstMediaTimeAfterSeek_WhenIsClosestIsTrue, TestSize.Level0)
{
    syncManager_->minRangeStartOfMediaTime_ = 0;
    syncManager_->maxRangeEndOfMediaTime_ = 100;
    EXPECT_EQ(syncManager_->Seek(50, true), Status::OK);
    EXPECT_EQ(syncManager_->firstMediaTimeAfterSeek_, 50);
}

// Scenario4: Seek when isClosest is false
HWTEST_F(TestSyncManager, Seek_ShouldSetFirstMediaTimeAfterSeekToNone_WhenIsClosestIsFalse, TestSize.Level0)
{
    syncManager_->minRangeStartOfMediaTime_ = 0;
    syncManager_->maxRangeEndOfMediaTime_ = 100;
    EXPECT_EQ(syncManager_->Seek(50, false), Status::OK);
    EXPECT_EQ(syncManager_->firstMediaTimeAfterSeek_, HST_TIME_NONE);
}

// Scenario1: Test when syncer is nullptr then AddSynchronizer does nothing.
HWTEST_F(TestSyncManager, AddSynchronizer_ShouldDoNothing_WhenSyncerIsNull, TestSize.Level0)
{
    IMediaSynchronizer* syncer = nullptr;
    syncManager_->AddSynchronizer(syncer);
    // No exception should be thrown and no action should be performed.
    EXPECT_EQ(syncManager_->syncers_.size(), 0);
}

// Scenario2: Test when syncer is not nullptr and not already in syncers_ then AddSynchronizer adds the syncer.
HWTEST_F(TestSyncManager, AddSynchronizer_ShouldAddSyncer_WhenSyncerIsNotNullAndNotInSyncers, TestSize.Level0)
{
    IMediaSynchronizer* syncer = new VideoSink();
    syncManager_->AddSynchronizer(syncer);
    EXPECT_EQ(syncManager_->syncers_.size(), 1);
    EXPECT_EQ(syncManager_->syncers_[0], syncer);
    delete syncer;
}

// Scenario3: Test when syncer is not nullptr and already in syncers_ then AddSynchronizer does nothing.
HWTEST_F(TestSyncManager, AddSynchronizer_ShouldDoNothing_WhenSyncerIsNotNullAndInSyncers, TestSize.Level0)
{
    IMediaSynchronizer* syncer = new VideoSink();
    syncManager_->AddSynchronizer(syncer);
    syncManager_->AddSynchronizer(syncer);
    EXPECT_EQ(syncManager_->syncers_.size(), 1);
    delete syncer;
}

// Scenario2: Test when syncer is not nullptr then RemoveSynchronizer removes the syncer from syncManager.
HWTEST_F(TestSyncManager, RemoveSynchronizer_ShouldRemoveSyncer_WhenSyncerIsNotNull, TestSize.Level0)
{
    IMediaSynchronizer* syncer = new VideoSink();
    IMediaSynchronizer* syncerOne = new VideoSink();
    syncManager_->AddSynchronizer(syncer);
    syncManager_->RemoveSynchronizer(syncerOne);
    EXPECT_EQ(syncManager_->syncers_.size(), 1);
    syncManager_->RemoveSynchronizer(syncer);
    EXPECT_EQ(syncManager_->syncers_.size(), 0);
    delete syncer;
    delete syncerOne;
}

// Scenario1: Test case for rate less than 0
HWTEST_F(TestSyncManager, SetPlaybackRate_ShouldReturnError_WhenRateLessThan0, TestSize.Level0) {
    float rate = -1.0;
    EXPECT_EQ(syncManager_->SetPlaybackRate(rate), Status::ERROR_INVALID_PARAMETER);
}

// Scenario2: Test case for rate equal to 0
HWTEST_F(TestSyncManager, SetPlaybackRate_ShouldReturnOk_WhenRateEqualTo0, TestSize.Level0) {
    float rate = 0.0;
    EXPECT_EQ(syncManager_->SetPlaybackRate(rate), Status::OK);
}

// Scenario3: Test case for rate greater than 0 and currentAnchorMediaTime_ is HST_TIME_NONE
HWTEST_F(TestSyncManager,
    SetPlaybackRate_ShouldReturnOk_WhenRateGreaterThan0AndCurrentAnchorMediaTimeIsNone, TestSize.Level0) {
    float rate = 1.0;
    syncManager_->currentAnchorMediaTime_ = HST_TIME_NONE;
    EXPECT_EQ(syncManager_->SetPlaybackRate(rate), Status::OK);
}

// Scenario4: Test case for rate greater than 0 and currentAnchorMediaTime_ is not HST_TIME_NONE
HWTEST_F(TestSyncManager,
    SetPlaybackRate_ShouldReturnOk_WhenRateGreaterThan0AndCurrentAnchorMediaTimeIsNotNone, TestSize.Level0) {
    float rate = 1.0;
    syncManager_->currentAnchorMediaTime_ = 100;
    EXPECT_EQ(syncManager_->SetPlaybackRate(rate), Status::OK);
}

HWTEST_F(TestSyncManager, UpdateFirstPtsAfterSeek_ShouldUpdateFirstPts_WhenFirstPtsIsNone, TestSize.Level0)
{
    int64_t mediaTime = 100;
    syncManager_->UpdateFirstPtsAfterSeek(mediaTime);
    EXPECT_EQ(syncManager_->firstMediaTimeAfterSeek_, mediaTime);
}

HWTEST_F(TestSyncManager, UpdateFirstPtsAfterSeek_ShouldUpdateFirstPts_WhenMediaTimeIsGreater, TestSize.Level0)
{
    int64_t firstMediaTimeAfterSeek = 50;
    int64_t mediaTime = 100;
    syncManager_->firstMediaTimeAfterSeek_ = firstMediaTimeAfterSeek;
    syncManager_->UpdateFirstPtsAfterSeek(mediaTime);
    EXPECT_EQ(syncManager_->firstMediaTimeAfterSeek_, mediaTime);
}

HWTEST_F(TestSyncManager, UpdateFirstPtsAfterSeek_ShouldNotUpdateFirstPts_WhenMediaTimeIsLess, TestSize.Level0)
{
    int64_t firstMediaTimeAfterSeek = 150;
    int64_t mediaTime = 100;
    syncManager_->firstMediaTimeAfterSeek_ = firstMediaTimeAfterSeek;
    syncManager_->UpdateFirstPtsAfterSeek(mediaTime);
    EXPECT_EQ(syncManager_->firstMediaTimeAfterSeek_, firstMediaTimeAfterSeek);
}

HWTEST_F(TestSyncManager, GetMediaTime_001, TestSize.Level0)
{
    syncManager_->currentAnchorClockTime_ = 100;
    syncManager_->delayTime_ = 50;
    syncManager_->currentAnchorMediaTime_ = 200;
    syncManager_->playRate_ = 0;
    int64_t clockTime = 150;
    int64_t result = syncManager_->GetMediaTime(clockTime);
    ASSERT_EQ(result, HST_TIME_NONE);
}

HWTEST_F(TestSyncManager, GetMediaTime_002, TestSize.Level0)
{
    syncManager_->currentAnchorClockTime_ = HST_TIME_NONE;
    syncManager_->delayTime_ = 50;
    syncManager_->currentAnchorMediaTime_ = 200;
    syncManager_->playRate_ = 1.0;
    int64_t clockTime = 150;
    int64_t result = syncManager_->GetMediaTime(clockTime);
    ASSERT_EQ(result, HST_TIME_NONE);
}

HWTEST_F(TestSyncManager, GetMediaTime_003, TestSize.Level0)
{
    syncManager_->currentAnchorClockTime_ = 100;
    syncManager_->delayTime_ = 50;
    syncManager_->currentAnchorMediaTime_ = 200;
    syncManager_->playRate_ = 1.0;
    int64_t clockTime = 150;
    int64_t result = syncManager_->GetMediaTime(clockTime);
    ASSERT_EQ(result, 250);
}

HWTEST_F(TestSyncManager, GetAnchoredClockTime_001, TestSize.Level0)
{
    MediaSyncManager mediaSyncManager;
    mediaSyncManager.minRangeStartOfMediaTime_ = 100;
    mediaSyncManager.maxRangeEndOfMediaTime_ = 200;
    int64_t mediaTime = 50;
    int64_t result = mediaSyncManager.GetAnchoredClockTime(mediaTime);
    EXPECT_EQ(result, HST_TIME_NONE);
}

// Scenario2: Test when mediaTime is greater than maxRangeEndOfMediaTime_
HWTEST_F(TestSyncManager, GetAnchoredClockTime_002, TestSize.Level0)
{
    MediaSyncManager mediaSyncManager;
    mediaSyncManager.minRangeStartOfMediaTime_ = 100;
    mediaSyncManager.maxRangeEndOfMediaTime_ = 200;
    int64_t mediaTime = 250;
    int64_t result = mediaSyncManager.GetAnchoredClockTime(mediaTime);
    EXPECT_EQ(result, HST_TIME_NONE);
}

// Scenario3: Test when mediaTime is within the range
HWTEST_F(TestSyncManager, GetAnchoredClockTime_003, TestSize.Level0)
{
    MediaSyncManager mediaSyncManager;
    mediaSyncManager.minRangeStartOfMediaTime_ = 100;
    mediaSyncManager.maxRangeEndOfMediaTime_ = 200;
    int64_t mediaTime = 150;
    int64_t result = mediaSyncManager.GetAnchoredClockTime(mediaTime);
    EXPECT_EQ(result, HST_TIME_NONE);
}

// Scenario1: audio priority and not seeked, do not go back
HWTEST_F(TestSyncManager, BoundMediaProgress_001, TestSize.Level0)
{
    MediaSyncManager mediaSyncManager;
    int64_t newMediaProgressTime;
    int64_t lastReportMediaTime = 90;
    // pre-defined values
    mediaSyncManager.lastAudioBufferDuration_ = 20;
    mediaSyncManager.currentAnchorMediaTime_ = 100;
    mediaSyncManager.lastReportMediaTime_ = lastReportMediaTime;
    mediaSyncManager.isFrameAfterSeeked_ = false;
    mediaSyncManager.currentSyncerPriority_ = IMediaSynchronizer::AUDIO_SINK;

    newMediaProgressTime = 50;
    auto result = mediaSyncManager.BoundMediaProgress(newMediaProgressTime);
    ASSERT_EQ(result, lastReportMediaTime);
}

// Scenario2: audio priority and not seeked, do not go too far
HWTEST_F(TestSyncManager, BoundMediaProgress_002, TestSize.Level0)
{
    MediaSyncManager mediaSyncManager;
    int64_t newMediaProgressTime;
    // pre-defined values
    mediaSyncManager.lastAudioBufferDuration_ = 20;
    mediaSyncManager.currentAnchorMediaTime_ = 100;
    mediaSyncManager.lastReportMediaTime_ = 90;
    mediaSyncManager.isFrameAfterSeeked_ = false;
    mediaSyncManager.currentSyncerPriority_ = IMediaSynchronizer::AUDIO_SINK;

    newMediaProgressTime = 250;
    auto result = mediaSyncManager.BoundMediaProgress(newMediaProgressTime);
    ASSERT_EQ(result, mediaSyncManager.currentAnchorMediaTime_ + mediaSyncManager.lastAudioBufferDuration_);
}

// Scenario3: audio priority and not seeked, progress is valid
HWTEST_F(TestSyncManager, BoundMediaProgress_003, TestSize.Level0)
{
    MediaSyncManager mediaSyncManager;
    int64_t newMediaProgressTime;
    // pre-defined values
    mediaSyncManager.lastAudioBufferDuration_ = 20;
    mediaSyncManager.currentAnchorMediaTime_ = 100;
    mediaSyncManager.lastReportMediaTime_ = 90;
    mediaSyncManager.isFrameAfterSeeked_ = false;
    mediaSyncManager.currentSyncerPriority_ = IMediaSynchronizer::AUDIO_SINK;

    newMediaProgressTime = 100;
    auto result = mediaSyncManager.BoundMediaProgress(newMediaProgressTime);
    ASSERT_EQ(result, newMediaProgressTime);
}

// Scenario4: non-audio priority and seeked, go back after seek
HWTEST_F(TestSyncManager, BoundMediaProgress_004, TestSize.Level0)
{
    MediaSyncManager mediaSyncManager;
    int64_t newMediaProgressTime;
    // pre-defined values
    mediaSyncManager.lastAudioBufferDuration_ = 100;
    mediaSyncManager.currentAnchorMediaTime_ = 100;
    mediaSyncManager.lastReportMediaTime_ = 150;
    mediaSyncManager.isFrameAfterSeeked_ = true;
    mediaSyncManager.currentSyncerPriority_ = IMediaSynchronizer::SUBTITLE_SINK;

    newMediaProgressTime = 50;
    auto result = mediaSyncManager.BoundMediaProgress(newMediaProgressTime);
    ASSERT_EQ(result, newMediaProgressTime);
}

// Scenario5: non-audio priority and seeked, go forward after seek
HWTEST_F(TestSyncManager, BoundMediaProgress_005, TestSize.Level0)
{
    MediaSyncManager mediaSyncManager;
    int64_t newMediaProgressTime;
    // pre-defined values
    mediaSyncManager.currentAnchorMediaTime_ = 200;
    mediaSyncManager.lastReportMediaTime_ = 150;
    mediaSyncManager.isFrameAfterSeeked_ = true;
    mediaSyncManager.currentSyncerPriority_ = IMediaSynchronizer::SUBTITLE_SINK;

    newMediaProgressTime = 175;
    auto result = mediaSyncManager.BoundMediaProgress(newMediaProgressTime);
    ASSERT_EQ(result, newMediaProgressTime);
}

// Scenario6: video audio priority and seeked, go forward after seek
HWTEST_F(TestSyncManager, BoundMediaProgress_006, TestSize.Level0)
{
    MediaSyncManager mediaSyncManager;
    int64_t newMediaProgressTime;
    // pre-defined values
    mediaSyncManager.lastVideoBufferPts_ = 0;
    mediaSyncManager.currentSyncerPriority_ = IMediaSynchronizer::VIDEO_SINK;
    newMediaProgressTime = 175;
    auto result = mediaSyncManager.BoundMediaProgress(newMediaProgressTime);
    ASSERT_EQ(result, mediaSyncManager.lastVideoBufferPts_);
}

// Scenario1: Test case when isSeeking_ is true
HWTEST_F(TestSyncManager, GetMediaTimeNow_001, TestSize.Level0)
{
    MediaSyncManager mediaSyncManager;
    int64_t seekingMediaTime = 100;
    mediaSyncManager.isSeeking_ = true;
    mediaSyncManager.seekingMediaTime_ = seekingMediaTime;
    EXPECT_EQ(mediaSyncManager.GetMediaTimeNow(), seekingMediaTime);
}

// Scenario2: Test case when paused
HWTEST_F(TestSyncManager, GetMediaTimeNow_002, TestSize.Level0)
{
    MediaSyncManager mediaSyncManager;
    mediaSyncManager.isSeeking_ = false;
    mediaSyncManager.lastReportMediaTime_ = 100;
    mediaSyncManager.pausedMediaTime_ = 120;
    mediaSyncManager.currentAnchorMediaTime_ = 150;
    mediaSyncManager.isFrameAfterSeeked_ = false;
    mediaSyncManager.firstMediaTimeAfterSeek_ = 50;
    mediaSyncManager.clockState_ = MediaSyncManager::State::PAUSED;
    mediaSyncManager.startPts_ = 0;
    mediaSyncManager.currentSyncerPriority_ = IMediaSynchronizer::SUBTITLE_SINK;
    int64_t result = mediaSyncManager.GetMediaTimeNow();
    EXPECT_EQ(result, mediaSyncManager.pausedMediaTime_);
}

// Scenario3: Test case when invalid
HWTEST_F(TestSyncManager, GetMediaTimeNow_003, TestSize.Level0)
{
    MediaSyncManager mediaSyncManager;
    mediaSyncManager.isSeeking_ = false;
    mediaSyncManager.clockState_ = MediaSyncManager::State::RESUMED;
    mediaSyncManager.startPts_ = 0;
    mediaSyncManager.currentAnchorClockTime_ = HST_TIME_NONE;
    int64_t result = mediaSyncManager.GetMediaTimeNow();
    EXPECT_EQ(result, 0);
}

// Scenario4: Test for normal case1
HWTEST_F(TestSyncManager, GetMediaTimeNow_004, TestSize.Level0)
{
    MediaSyncManager mediaSyncManager;
    int64_t lastReportMediaTime_ = 110;
    mediaSyncManager.isSeeking_ = false;
    mediaSyncManager.clockState_ = MediaSyncManager::State::RESUMED;
    mediaSyncManager.lastReportMediaTime_ = lastReportMediaTime_;
    mediaSyncManager.currentAnchorMediaTime_ = 150;
    mediaSyncManager.delayTime_ = 50;
    mediaSyncManager.playRate_ = 1.0f;
    mediaSyncManager.isFrameAfterSeeked_ = false;
    mediaSyncManager.firstMediaTimeAfterSeek_ = 50; // firstMediaTimeAfterSeek_ < currentMediaTime
    mediaSyncManager.startPts_ = 0;
    mediaSyncManager.currentSyncerPriority_ = IMediaSynchronizer::SUBTITLE_SINK;
    mediaSyncManager.currentAnchorClockTime_ = mediaSyncManager.GetSystemClock();
    int64_t result = mediaSyncManager.GetMediaTimeNow();
    EXPECT_EQ(result >= lastReportMediaTime_, true);
    EXPECT_EQ(result <= mediaSyncManager.currentAnchorMediaTime_, true);
}

// Scenario5: Test for normal case2
HWTEST_F(TestSyncManager, GetMediaTimeNow_005, TestSize.Level0)
{
    MediaSyncManager mediaSyncManager;
    int64_t lastReportMediaTime_ = 110;
    mediaSyncManager.isSeeking_ = false;
    mediaSyncManager.clockState_ = MediaSyncManager::State::RESUMED;
    mediaSyncManager.lastReportMediaTime_ = lastReportMediaTime_;
    mediaSyncManager.currentAnchorMediaTime_ = 150;
    mediaSyncManager.delayTime_ = 50;
    mediaSyncManager.playRate_ = 1.0f;
    mediaSyncManager.isFrameAfterSeeked_ = false;
    mediaSyncManager.firstMediaTimeAfterSeek_ = 150; // firstMediaTimeAfterSeek_ >= currentMediaTime
    mediaSyncManager.startPts_ = 0;
    mediaSyncManager.currentSyncerPriority_ = IMediaSynchronizer::SUBTITLE_SINK;
    mediaSyncManager.currentAnchorClockTime_ = mediaSyncManager.GetSystemClock();
    int64_t result = mediaSyncManager.GetMediaTimeNow();
    EXPECT_EQ(result >= lastReportMediaTime_, true);
    EXPECT_EQ(result <= mediaSyncManager.currentAnchorMediaTime_, true);
}

// Scenario6: Test for normal case3
HWTEST_F(TestSyncManager, GetMediaTimeNow_006, TestSize.Level0)
{
    MediaSyncManager mediaSyncManager;
    int64_t lastReportMediaTime_ = 110;
    mediaSyncManager.isSeeking_ = false;
    mediaSyncManager.clockState_ = MediaSyncManager::State::RESUMED;
    mediaSyncManager.lastReportMediaTime_ = lastReportMediaTime_;
    mediaSyncManager.currentAnchorMediaTime_ = 150;
    mediaSyncManager.delayTime_ = 50;
    mediaSyncManager.playRate_ = 1.0f;
    mediaSyncManager.isFrameAfterSeeked_ = false;
    mediaSyncManager.firstMediaTimeAfterSeek_ = HST_TIME_NONE; // firstMediaTimeAfterSeek_ = HST_TIME_NONE
    mediaSyncManager.startPts_ = 0;
    mediaSyncManager.currentSyncerPriority_ = IMediaSynchronizer::SUBTITLE_SINK;
    mediaSyncManager.currentAnchorClockTime_ = mediaSyncManager.GetSystemClock();
    int64_t result = mediaSyncManager.GetMediaTimeNow();
    EXPECT_EQ(result >= lastReportMediaTime_, true);
    EXPECT_EQ(result <= mediaSyncManager.currentAnchorMediaTime_, true);
}

HWTEST_F(TestSyncManager, GetMediaTimeNow_007, TestSize.Level0)
{
    syncManager_->isSeeking_ = false;
    syncManager_->clockState_ = MediaSyncManager::State::PAUSED;
    syncManager_->pausedMediaTime_ = 50;
    syncManager_->firstMediaTimeAfterSeek_ = 150;
    syncManager_->startPts_ = 50;
    syncManager_->currentSyncerPriority_ = IMediaSynchronizer::SUBTITLE_SINK;
    syncManager_->currentAnchorMediaTime_ = 50;
    EXPECT_EQ(syncManager_->GetMediaTimeNow(), 50);
}

HWTEST_F(TestSyncManager, GetMediaTimeNow_008, TestSize.Level0)
{
    syncManager_->isSeeking_ = false;
    syncManager_->clockState_ = MediaSyncManager::State::PAUSED;
    syncManager_->pausedMediaTime_ = 100;
    syncManager_->firstMediaTimeAfterSeek_ = 150;
    syncManager_->currentSyncerPriority_ = IMediaSynchronizer::SUBTITLE_SINK;
    syncManager_->currentAnchorMediaTime_ = 50;
    EXPECT_EQ(syncManager_->GetMediaTimeNow(), 50);
}

HWTEST_F(TestSyncManager, SetLastAudioBufferDuration_001, TestSize.Level0)
{
    syncManager_->SetLastAudioBufferDuration(50);
    EXPECT_EQ(syncManager_->lastAudioBufferDuration_, 50);
    syncManager_->SetLastAudioBufferDuration(0);
    EXPECT_EQ(syncManager_->lastAudioBufferDuration_, 0);
}

// Scenario1: Test when startPts is less than startPts_ then startPts_ should be updated.
HWTEST_F(TestSyncManager, SetMediaStartPts_ShouldUpdateStartPts_WhenStartPtsIsLess, TestSize.Level0)
{
    syncManager_->SetMediaStartPts(100);
    syncManager_->SetMediaStartPts(50);
    EXPECT_EQ(syncManager_->startPts_, 50);
}

// Scenario2: Test when startPts is equal to startPts_ then startPts_ should not be updated.
HWTEST_F(TestSyncManager, SetMediaStartPts_ShouldNotUpdateStartPts_WhenStartPtsIsEqual, TestSize.Level0)
{
    syncManager_->SetMediaStartPts(100);
    syncManager_->SetMediaStartPts(100);
    EXPECT_EQ(syncManager_->startPts_, 100);
}

// Scenario3: Test when startPts is HST_TIME_NONE then startPts_ should be updated.
HWTEST_F(TestSyncManager, SetMediaStartPts_ShouldUpdateStartPts_WhenStartPtsIsNone, TestSize.Level0)
{
    syncManager_->SetMediaStartPts(HST_TIME_NONE);
    EXPECT_EQ(syncManager_->startPts_, HST_TIME_NONE);
}

// Scenario1: Test when supplier is nullptr then ReportPrerolled returns immediately.
HWTEST_F(TestSyncManager, ReportPrerolled_001, TestSize.Level0)
{
    syncManager_->ReportPrerolled(nullptr);
    // No further action is expected, as the function should return immediately.
    EXPECT_EQ(syncManager_->prerolledSyncers_.size(), 0);
}

// Scenario3: Test when supplier is already in prerolledSyncers_ then ReportPrerolled returns immediately.
HWTEST_F(TestSyncManager, ReportPrerolled_003, TestSize.Level0)
{
    IMediaSynchronizer* supplier = new VideoSink();
    syncManager_->prerolledSyncers_.emplace_back(supplier);
    syncManager_->ReportPrerolled(supplier);
    // No further action is expected, as the function should return immediately.
    EXPECT_EQ(syncManager_->prerolledSyncers_.size(), 1);
    delete supplier;
}

HWTEST_F(TestSyncManager, ReportPrerolled_004, TestSize.Level0)
{
    IMediaSynchronizer* supplier = new VideoSink();
    syncManager_->ReportPrerolled(supplier);
    EXPECT_EQ(syncManager_->prerolledSyncers_.size(), 1);
    EXPECT_EQ(syncManager_->prerolledSyncers_.front(), supplier);
    delete supplier;
}

// Scenario5: Test when all prerolledSyncers_ are equal to syncers_ then all prerolledSyncers_ are notified and cleared.
HWTEST_F(TestSyncManager, ReportPrerolled_005, TestSize.Level0)
{
    IMediaSynchronizer* supplier = new VideoSink();
    syncManager_->syncers_.emplace_back(supplier);
    syncManager_->ReportPrerolled(supplier);
    EXPECT_EQ(syncManager_->prerolledSyncers_.size(), 0);
    EXPECT_EQ(syncManager_->prerolledSyncers_.size(), 0);
    delete supplier;
}
}  // namespace Test
}  // namespace Media
}  // namespace OHOS